#include "texturebillboardeffect.h"
#include "stringproperty.h"
#include "datatypedefine.h"
#include "transformableactor.h"
#include <osg\StateSet>
#include <osg\Node>
#include <osg\BlendFunc>
#include <osg\ComputeBoundsVisitor>
#include "resourceloader.h"
#include <osg\ImageStream>
#include <osg\Texture2D>
#include "vectorproperties.h"
#include "numberproperty.h"
#include <osg\CullFace>

namespace VrDataCore
{
	TextureBillboardEffect::TextureBillboardEffect():_iconFile("billboard\\demo.gif"),_size(2.5f)
	{
		createBillboardNode();
		setClassName(CLASS_EFFECT_TEXTUREBILLBOARD);
	}

	TextureBillboardEffect::~TextureBillboardEffect()
	{}

	void TextureBillboardEffect::buildPropertyMap()
	{
		EffectBase::buildPropertyMap();
		addProperty(new StringProperty<TextureBillboardEffect>(XML_ELEMENT_DATATYPE_STRING,ACTOR_PROPERYT_TEXTURE,
			"图片",this,&TextureBillboardEffect::setBillboardTexture,&TextureBillboardEffect::getBillboardTexture,
			ACTOR_DESC_BINDING_GUI,ACTOR_GROUP_GUI_TEXTURE));
		addProperty(new Vec3fProperty<TextureBillboardEffect>(XML_ELEMENT_DATATYPE_VEC3F,
			ACTOR_PROPERYT_TRANSLATION,"平移",this,&TextureBillboardEffect::setPosition,
			&TextureBillboardEffect::getPosition,ACTOR_DESC_BINDING_GUI,ACTOR_GROUP_GUI_VEC3));
		addProperty(new FloatProperty<TextureBillboardEffect>(XML_ELEMENT_DATATYPE_FLOAT,
			"大小","",this,&TextureBillboardEffect::setSize,
			&TextureBillboardEffect::getSize,ACTOR_DESC_BINDING_GUI,ACTOR_GROUP_GUI_NUMTEXT));
	}

	void TextureBillboardEffect::setBillboardTexture(QString texture)
	{
		if(_iconFile!=texture)
		{
			unApply(_bindingMeshDrawableActor);
			_iconFile = texture;
			if(_bindingMeshDrawableActor!=NULL)
				apply(_bindingMeshDrawableActor);
		}
	}

	QString TextureBillboardEffect::getBillboardTexture()
	{
		return _iconFile;
	}

	void TextureBillboardEffect::apply(CoreBase::ActorBase* actor)
	{
		if(!isIdle())
			return;
		_bindingMeshDrawableActor = actor;
		//osg::BoundingBox planebb;
		//osg::ref_ptr<osg::ComputeBoundsVisitor> boundsVistor = new osg::ComputeBoundsVisitor();
		//boundsVistor->reset() ;
		//actor->getDrawable()->getOSGNode()->asGroup()->accept(*boundsVistor.get());
		//planebb = boundsVistor->getBoundingBox();
		//_billboardTransform->setPosition(osg::Vec3(0,0,planebb.zMax()+2.0f));
		_bindingMeshDrawableActor->getDrawable()->getOSGNode()->asGroup()->addChild(_billboardTransform);
		osg::StateSet* ss = _geometry->getOrCreateStateSet();
		osg::ref_ptr<osg::Texture2D> texture = CoreBase::ResourceLoader::GetInstance().getTextureByFileName(_iconFile);
		if(texture.valid())
		{
			ss->setTextureAttributeAndModes(0,texture.get(),osg::StateAttribute::ON);
			osg::BlendFunc* bf = new osg::BlendFunc(osg::BlendFunc::SRC_ALPHA,osg::BlendFunc::ONE_MINUS_SRC_ALPHA );
			ss->setAttributeAndModes(bf);
			ss->setRenderingHint(osg::StateSet::TRANSPARENT_BIN);
			if(dynamic_cast<osg::ImageStream*>(texture->getImage(0))!=NULL)
			{
				//dynamic_cast<osg::ImageStream*>(texture->getImage(0))->setTimeMultiplier(3);
				dynamic_cast<osg::ImageStream*>(texture->getImage(0))->play();
			}
		}
		EffectBase::apply(actor);
	}

	void TextureBillboardEffect::unApply( CoreBase::ActorBase* actor)
	{
		if(isIdle())
			return;
		_bindingMeshDrawableActor->getDrawable()->getOSGNode()->asGroup()->removeChild(_billboardTransform);
		EffectBase::unApply(actor);
	}

	void TextureBillboardEffect::createBillboardNode()
	{
		_billboard = new osg::Billboard();
		_billboard->setMode(osg::Billboard::POINT_ROT_WORLD);
		//_billboard->setAxis(osg::Vec3(0.0f,0.0f,1.0f));
		osg::StateSet* ss = _billboard->getOrCreateStateSet();
		ss->setMode(GL_LIGHTING,osg::StateAttribute::OFF);
		ss->setMode(GL_BLEND, osg::StateAttribute::ON);
		_array = new osg::Vec3Array();
		_array->push_back(osg::Vec3(-_size,0.0,-_size));
		_array->push_back(osg::Vec3(_size,0.0,-_size));
		_array->push_back(osg::Vec3(_size,0.0,_size));
		_array->push_back(osg::Vec3(-_size,0.0,_size));
		_geometry = new osg::Geometry();
		_geometry->setVertexArray(_array.get());
		osg::ref_ptr<osg::Vec3Array> normal = new osg::Vec3Array();
		normal->push_back(osg::Vec3(1.0f,0.0f,0.0f)^osg::Vec3(0.0f,0.0f,1.0f));
		_geometry->setNormalArray(normal.get());
		_geometry->setNormalBinding(osg::Geometry::BIND_OVERALL);
		osg::ref_ptr<osg::Vec2Array> coord = new osg::Vec2Array();
		coord->push_back(osg::Vec2(0.0f,0.0f));
		coord->push_back(osg::Vec2(1.0f,0.0f));
		coord->push_back(osg::Vec2(1.0f,1.0f));
		coord->push_back(osg::Vec2(0.0f,1.0f));
		_geometry->setTexCoordArray(0,coord.get());
		osg::Vec4Array* colorArray = new osg::Vec4Array;
		colorArray->push_back(osg::Vec4(1.0f, 1.0f, 1.0f, 1.0f) );
		osg::TemplateIndexArray<unsigned int, osg::Array::UIntArrayType,4,1> *colorIndexArray;
		colorIndexArray = new osg::TemplateIndexArray<unsigned int, osg::Array::UIntArrayType,4,1>;
		colorIndexArray->push_back(0);
		// 使用索引数组将其中的第一个值关联给所有的顶点。
		_geometry->setColorArray( colorArray);
		_geometry->setColorIndices(colorIndexArray);
		_geometry->setColorBinding(osg::Geometry::BIND_OVERALL);
		_geometry->addPrimitiveSet(new osg::DrawArrays(osg::PrimitiveSet::QUADS,0,4));
		_billboard->addDrawable(_geometry.get(),osg::Vec3(0,0,0));
		_billboardTransform = new osg::PositionAttitudeTransform;
		_billboardTransform->addChild(_billboard); 
	}

	void TextureBillboardEffect::setSize(float size)
	{
		_size = size;
		osg::Vec3Array* varray = dynamic_cast<osg::Vec3Array*>(_geometry->getVertexArray());
		varray->clear();
		varray->push_back(osg::Vec3(-_size,0.0,-_size));
		varray->push_back(osg::Vec3(_size,0.0,-_size));
		varray->push_back(osg::Vec3(_size,0.0,_size));
		varray->push_back(osg::Vec3(-_size,0.0,_size));
		_geometry->setVertexArray(varray);
	}

	float TextureBillboardEffect::getSize()
	{
		return _size;
	}

	void TextureBillboardEffect::setPosition(osg::Vec3 pos)
	{
		_position = pos;
		_billboardTransform->setPosition(_position);
	}
		
	osg::Vec3 TextureBillboardEffect::getPosition()
	{
		return _position;
	}
}